﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using RabbitMQ.Client;

namespace HYService.RabbitMQ
{
    public class RabbitBus
    {
        /// <summary>
        /// 连接字符串(结尾没有分号)
        /// amqp://username:password@host:port/virtualhost
        /// </summary>
        internal static string ConnectionString
        {
            get
            {
                var url = ConfigurationManager.AppSettings["RabbitMQURL"];
                if (url == null)
                {
                    throw new Exception("请添加名称为RabbitMQURL的配置项");
                }

                if (string.IsNullOrEmpty(url))
                {
                    throw new Exception("请为名称为RabbitMQURL的配置项设置有效的值");
                }

                return url;
            }
        }

        public static IConnection CreateConnection()
        {
            ConnectionFactory factory = new ConnectionFactory();
            factory.Uri = RabbitBus.ConnectionString;
            factory.TopologyRecoveryEnabled = true;
            factory.AutomaticRecoveryEnabled = true;
            factory.NetworkRecoveryInterval = TimeSpan.FromSeconds(60);
            SetDefaultClientProperties(factory);
            return factory.CreateConnection();
        }

        private static void SetDefaultClientProperties(ConnectionFactory factory)
        {
            var applicationName = "unknown";
            var applicationPath = "unknown";
            var applicationNameAndPath = Environment.GetCommandLineArgs()[0];
            if (!string.IsNullOrWhiteSpace(applicationNameAndPath))
            {
                // Note: When running the application in an Integration Services Package (SSIS) the
                // Environment.GetCommandLineArgs()[0] can return null, and therefor it is not possible to get
                // the filename or directory name.
                try
                {
                    // Will only throw an exception if the applicationName contains invalid characters, is empty, or too long
                    // Silently catch the exception, as we will just leave the application name and path to "unknown"
                    applicationName = Path.GetFileName(applicationNameAndPath);
                    applicationPath = Path.GetDirectoryName(applicationNameAndPath);
                }
                catch (ArgumentException) { }
                catch (PathTooLongException) { }
            }

            var clientProperties = factory.ClientProperties;
            clientProperties.Add("application", applicationName);
            clientProperties.Add("application_location", applicationPath);
            clientProperties.Add("machine_name", Environment.MachineName);
            clientProperties.Add("user", factory.UserName);
            clientProperties.Add("connected", DateTime.Now.ToString("u")); // UniversalSortableDateTimePattern: yyyy'-'MM'-'dd HH':'mm':'ss'Z'
            clientProperties.Add("requested_heartbeat", factory.RequestedHeartbeat.ToString());
            clientProperties.Add("timeout", factory.RequestedConnectionTimeout.ToString());
        }
    }
}
